package com.zhou.combine.security.config;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.zhou.combine.security.MenuMappingHandler;
import com.zhou.combine.security.entity.Menu;
import com.zhou.combine.security.mapper.MenuMapper;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.util.UrlPathHelper;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * MenuAuthFilter
 *
 * @author zhouxianfeng
 * @date 2021-1-8
 */
@Component
public class MenuAuthFilter implements Filter {

    private Logger logger=  LoggerFactory.getLogger(MenuAuthFilter.class);

    @Autowired
    private MenuMappingHandler menuMappingHandler;

    private UrlPathHelper urlPathHelper = new UrlPathHelper();

    @Value("${spring.application.name}")
    private String applicationName;

    @Autowired
    private MenuMapper menuMapper;

    private LoadingCache<RequestMappingInfo, Optional<Menu>> cache = CacheBuilder.newBuilder()
            .maximumSize(200)
            .expireAfterWrite(30, TimeUnit.MINUTES)
            .build(new CacheLoader<RequestMappingInfo, Optional<Menu>>() {
                @Override
                public Optional<Menu> load(RequestMappingInfo key) {
                    Set<String> directPaths = key.getPatternsCondition().getPatterns();
                    Set<RequestMethod> methods = key.getMethodsCondition().getMethods();
                    Menu newMenu=new Menu();
                    newMenu.setMethod(StringUtils.join(methods, ","));
                    newMenu.setPath(directPaths.iterator().next());
                    newMenu.setModule(applicationName);
                    LambdaQueryWrapper<Menu> queryWrapper=new LambdaQueryWrapper(newMenu);
                    Menu one = menuMapper.selectOne(queryWrapper);
                    return Optional.ofNullable(one);
                }
            });

    @SneakyThrows
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request=(HttpServletRequest) servletRequest;
        //通过请求的url，获取
        RequestMappingInfo info = menuMappingHandler.lookupHandlerMethod(urlPathHelper.resolveAndCacheLookupPath(request),  request);

        Optional<Menu> menu = cache.get(info);
        logger.info("当前资源的权限是：{}",menu);
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        logger.info("当前用户的权限是：{}",authorities);

    }
}
